#ifndef NETWORKUTILH
#define NETWORKUTILH

#ifndef INADDR_BROADCAST
#error "You need SDL_net 1.2.5 or newer to send broadcasts!"
#endif

struct User {
	string name;
	union {
		uint32 ip;
		uint8 ip4[4];
	};
};

void makePacketDataString(UDPpacket* packet, string str)
{
	if (str.size() > 512) str.resize(512);
	SDLNet_Write16((uint16)str.size(), &packet->data[packet->len]);
	packet->len += 2;
	memcpy(&packet->data[packet->len], str.c_str(), str.size());
	packet->len += str.size();
}

void makePacket1(UDPpacket* packet, string username)
{
	packet->len = 0;
	packet->data[packet->len++] = 1;
	makePacketDataString(packet, username);
}

void parsePacketDataString(UDPpacket* packet, string* str)
{
	uint16 len;
	len = SDLNet_Read16(&packet->data[packet->len]);
	packet->len += 2;
	*str = string(&packet->data[packet->len], &packet->data[packet->len+len]);
	packet->len += len;
}

void parsePacket1(UDPpacket* packet, string* username)
{
	packet->len = 0;
	assert(packet->data[packet->len++] == 1);
	parsePacketDataString(packet, username);
}

void parsePacket2(UDPpacket* packet, string* username, string* password)
{
	packet->len = 0;
	assert(packet->data[packet->len++] == 2);
	parsePacketDataString(packet, username);
	parsePacketDataString(packet, password);
}

void makePacket3(UDPpacket* packet, string username, string password)
{
	packet->len = 0;
	packet->data[packet->len++] = 3;
	makePacketDataString(packet, username);
	makePacketDataString(packet, password);
}

void parsePacket4(UDPpacket* packet, vector<User>* users)
{
	users->clear();
	packet->len = 0;
	assert(packet->data[packet->len++] == 4);
	uint16 numusers = SDLNet_Read16(&packet->data[packet->len]);
	packet->len += 2;

	for (int i = 0; i < numusers; ++i) {
		User user;
		parsePacketDataString(packet, &user.name);
		user.ip4[0] = packet->data[packet->len++];
		user.ip4[1] = packet->data[packet->len++];
		user.ip4[2] = packet->data[packet->len++];
		user.ip4[3] = packet->data[packet->len++];
		printf("parsed ip addr for %s : %i.%i.%i.%i\n", user.name.c_str(), user.ip4[0], user.ip4[1], user.ip4[2], user.ip4[3]);
		users->push_back(user);
	}
}

void makePacket5(UDPpacket* packet, uint8 type, uint32 fsize, uint32 portnum)
{
	packet->len = 0;
	packet->data[packet->len++] = 5;
	packet->data[packet->len++] = type;
	SDLNet_Write32(fsize,   &packet->data[packet->len]);  packet->len += 4;
	SDLNet_Write32(portnum, &packet->data[packet->len]);  packet->len += 4;
}

void parsePacket5(UDPpacket* packet, uint8* type, uint32* fsize, uint32* portnum)
{
	packet->len = 0;
	assert(packet->data[packet->len++] == 5);
	*type = packet->data[packet->len++];
	*fsize   = SDLNet_Read32(&packet->data[packet->len]);  packet->len += 4;
	*portnum = SDLNet_Read32(&packet->data[packet->len]);  packet->len += 4;
}

void makePacket6(UDPpacket* packet, uint8 type, uint32 fsize, uint32 portnum, string uname)
{
	packet->len = 0;
	packet->data[packet->len++] = 6;
	packet->data[packet->len++] = type;
	SDLNet_Write32(fsize,   &packet->data[packet->len]);  packet->len += 4;
	SDLNet_Write32(portnum, &packet->data[packet->len]);  packet->len += 4;
	makePacketDataString(packet, uname);
}

void parsePacket7(UDPpacket* packet, uint8* type, uint32* fsize, uint32* portnum, string* uname, uint32* tstamp)
{
	packet->len = 0;
	assert(packet->data[packet->len++] == 7);
	*type = packet->data[packet->len++];
	*fsize   = SDLNet_Read32(&packet->data[packet->len]);  packet->len += 4;
	*portnum = SDLNet_Read32(&packet->data[packet->len]);  packet->len += 4;
	parsePacketDataString(packet, uname);
	*tstamp  = SDLNet_Read32(&packet->data[packet->len]);  packet->len += 4;
}

void makeBroadcastPacket(UDPpacket* packet, uint16 port)
{
	static bool hax = false;
	if (!hax) {
		packet->address.host = 0xffffffff;
		packet->address.port = SDL_SwapBE16(port);
	}
	else
	{
		// hax :O
		SDLNet_ResolveHost(&packet->address, "fons.lan", port);
	}
	packet->channel = -1;
	//hax = !hax;
}

#endif
